home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / russell / gc.lha / debug_malloc.c < prev    next >
C/C++ Source or Header  |  1993-03-04  |  9KB  |  311 lines

  1. # include "gc_private.h"
  2. # define START_FLAG ((word)0xfedcedcb)
  3. # define END_FLAG ((word)0xbcdecdef)
  4.     /* Stored both one past the end of user object, and one before    */
  5.     /* the end of the object as seen by the allocator.        */
  6.  
  7. /* Object header */
  8. typedef struct {
  9.     char * oh_string;    /* object descriptor string    */
  10.     word oh_int;        /* object descriptor integers    */
  11.     word oh_sz;        /* Original malloc arg.        */
  12.     word oh_sf;            /* start flag */
  13. } oh;
  14. /* The size of the above structure is assumed not to dealign things,    */
  15. /* and to be a multiple of the word length.                */
  16.  
  17. #define DEBUG_BYTES (sizeof (oh) + sizeof (word))
  18. #define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
  19.  
  20. bool GC_debugging_started = FALSE;
  21.  
  22. /* Check whether object with base pointer p has debugging info    */ 
  23. /* p is assumed to point to a legitimate object in our part    */
  24. /* of the heap.                            */
  25. bool GC_has_debug_info(p)
  26. ptr_t p;
  27. {
  28.     register oh * ohdr = (oh *)p;
  29.     register ptr_t body = (ptr_t)(ohdr + 1);
  30.     register word sz = GC_size((ptr_t) ohdr);
  31.     
  32.     if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
  33.         || sz < sizeof (oh)) {
  34.         return(FALSE);
  35.     }
  36.     if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
  37.     if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
  38.         return(TRUE);
  39.     }
  40.     return(FALSE);
  41. }
  42.  
  43. /* Store debugging info into p.  Return displaced pointer. */
  44. /* Assumes we don't hold allocation lock.           */
  45. ptr_t GC_store_debug_info(p, sz, string, integer)
  46. register ptr_t p;    /* base pointer */
  47. word sz;     /* bytes */
  48. char * string;
  49. word integer;
  50. {
  51.     register word * result = (word *)((oh *)p + 1);
  52.     DCL_LOCK_STATE;
  53.     
  54.     /* There is some argument that we should dissble signals here.    */
  55.     /* But that's expensive.  And this way things should only appear    */
  56.     /* inconsistent while we're in the handler.                */
  57.     LOCK();
  58.     ((oh *)p) -> oh_string = string;
  59.     ((oh *)p) -> oh_int = integer;
  60.     ((oh *)p) -> oh_sz = sz;
  61.     ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
  62.     ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
  63.          result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
  64.     UNLOCK();
  65.     return((ptr_t)result);
  66. }
  67.  
  68. /* Check the object with debugging info at p         */
  69. /* return NIL if it's OK.  Else return clobbered    */
  70. /* address.                        */
  71. ptr_t GC_check_annotated_obj(ohdr)
  72. register oh * ohdr;
  73. {
  74.     register ptr_t body = (ptr_t)(ohdr + 1);
  75.     register word gc_sz = GC_size((ptr_t)ohdr);
  76.     if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
  77.         return((ptr_t)(&(ohdr -> oh_sz)));
  78.     }
  79.     if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
  80.         return((ptr_t)(&(ohdr -> oh_sf)));
  81.     }
  82.     if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
  83.         return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
  84.     }
  85.     if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
  86.         != (END_FLAG ^ (word)body)) {
  87.         return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
  88.     }
  89.     return(0);
  90. }
  91.  
  92. void GC_print_obj(p)
  93. ptr_t p;
  94. {
  95.     register oh * ohdr = (oh *)GC_base(p);
  96.     
  97.     GC_err_printf1("0x%lx (", (unsigned long)ohdr + sizeof(oh));
  98.     GC_err_puts(ohdr -> oh_string);
  99.     GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
  100.                           (unsigned long)(ohdr -> oh_sz));
  101. }
  102. void GC_print_smashed_obj(p, clobbered_addr)
  103. ptr_t p, clobbered_addr;
  104. {
  105.     register oh * ohdr = (oh *)GC_base(p);
  106.     
  107.     GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
  108.                                 (unsigned long)p);
  109.     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))) {
  110.         GC_err_printf1("<smashed>, appr. sz = %ld)\n",
  111.                    BYTES_TO_WORDS(GC_size((ptr_t)ohdr)));
  112.     } else {
  113.         GC_err_puts(ohdr -> oh_string);
  114.         GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
  115.                               (unsigned long)(ohdr -> oh_sz));
  116.     }
  117. }
  118.  
  119. # ifdef __STDC__
  120.     extern_ptr_t GC_debug_malloc(size_t lb, char * s, int i)
  121. # else
  122.     extern_ptr_t GC_debug_malloc(lb, s, i)
  123.     size_t lb;
  124.     char * s;
  125.     int i;
  126. # endif
  127. {
  128.     extern_ptr_t result = GC_malloc(lb + DEBUG_BYTES);
  129.     
  130.     if (result == 0) {
  131.         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
  132.                    (unsigned long) lb);
  133.         GC_err_puts(s);
  134.         GC_err_printf1(":%ld)\n", (unsigned long)i);
  135.         return(0);
  136.     }
  137.     if (!GC_debugging_started) {
  138.         GC_debugging_started = TRUE;
  139.         GC_register_displacement((word)sizeof(oh));
  140.     }
  141.     return (GC_store_debug_info(result, (word)lb, s, (word)i));
  142. }
  143.  
  144. # ifdef __STDC__
  145.     extern_ptr_t GC_debug_malloc_atomic(size_t lb, char * s, int i)
  146. # else
  147.     extern_ptr_t GC_debug_malloc_atomic(lb, s, i)
  148.     size_t lb;
  149.     char * s;
  150.     int i;
  151. # endif
  152. {
  153.     extern_ptr_t result = GC_malloc_atomic(lb + DEBUG_BYTES);
  154.     
  155.     if (result == 0) {
  156.         GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
  157.                   (unsigned long) lb);
  158.         GC_err_puts(s);
  159.         GC_err_printf1(":%ld)\n", (unsigned long)i);
  160.         return(0);
  161.     }
  162.     if (!GC_debugging_started) {
  163.         GC_debugging_started = TRUE;
  164.         GC_register_displacement((word)sizeof(oh));
  165.     }
  166.     return (GC_store_debug_info(result, (word)lb, s, (word)i));
  167. }
  168. # ifdef __STDC__
  169.     void GC_debug_free(extern_ptr_t p)
  170. # else
  171.     void GC_debug_free(p)
  172.     extern_ptr_t p;
  173. # endif
  174. {
  175.     register extern_ptr_t base = GC_base(p);
  176.     register ptr_t clobbered;
  177.     
  178.     if (base == 0) {
  179.         GC_err_printf1("Attempt to free invalid pointer %lx\n",
  180.                    (unsigned long)p);
  181.         ABORT("free(invalid pointer)");
  182.     }
  183.     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
  184.         GC_err_printf1(
  185.               "GC_debug_free called on pointer %lx wo debugging info\n",
  186.               (unsigned long)p);
  187.     } else {
  188.       clobbered = GC_check_annotated_obj((oh *)base);
  189.       if (clobbered != 0) {
  190.         GC_err_printf0("GC_debug_free: found smashed object at ");
  191.         GC_print_smashed_obj(p, clobbered);
  192.       }
  193.     }
  194.     GC_free(GC_base(p));
  195. }
  196.  
  197. # ifdef __STDC__
  198.     extern_ptr_t GC_debug_realloc(extern_ptr_t p, size_t lb, char *s, int i)
  199. # else
  200.     extern_ptr_t GC_debug_realloc(p, lb, s, i)
  201.     extern_ptr_t p;
  202.     size_t lb;
  203.     char *s;
  204.     int i;
  205. # endif
  206. {
  207.     register extern_ptr_t base = GC_base(p);
  208.     register ptr_t clobbered;
  209.     register extern_ptr_t result = GC_debug_malloc(lb, s, i);
  210.     register size_t copy_sz = lb;
  211.     register size_t old_sz;
  212.     
  213.     if (base == 0) {
  214.         GC_err_printf1(
  215.               "Attempt to free invalid pointer %lx\n", (unsigned long)p);
  216.         ABORT("realloc(invalid pointer)");
  217.     }
  218.     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
  219.         GC_err_printf1(
  220.             "GC_debug_realloc called on pointer %lx wo debugging info\n",
  221.             (unsigned long)p);
  222.         return(GC_realloc(p, lb));
  223.     }
  224.     clobbered = GC_check_annotated_obj((oh *)base);
  225.     if (clobbered != 0) {
  226.         GC_err_printf0("GC_debug_realloc: found smashed object at ");
  227.         GC_print_smashed_obj(p, clobbered);
  228.     }
  229.     old_sz = ((oh *)base) -> oh_sz;
  230.     if (old_sz < copy_sz) copy_sz = old_sz;
  231.     if (result == 0) return(0);
  232.     bcopy((char *)p, (char *)result, (int) copy_sz);
  233.     return(result);
  234. }
  235.  
  236. /* Check all marked objects in the given block for validity */
  237. /*ARGSUSED*/
  238. void GC_check_heap_block(hbp, dummy)
  239. register struct hblk *hbp;    /* ptr to current heap block        */
  240. word dummy;
  241. {
  242.     register struct hblkhdr * hhdr = HDR(hbp);
  243.     register word sz = hhdr -> hb_sz;
  244.     register int word_no;
  245.     register word *p, *plim;
  246.     
  247.     p = (word *)(hbp->hb_body);
  248.     word_no = HDR_WORDS;
  249.     plim = (word *)((((word)hbp) + HBLKSIZE)
  250.            - WORDS_TO_BYTES(sz));
  251.  
  252.     /* go through all words in block */
  253.     do {
  254.         if( mark_bit_from_hdr(hhdr, word_no)
  255.             && GC_has_debug_info((ptr_t)p)) {
  256.             ptr_t clobbered = GC_check_annotated_obj((oh *)p);
  257.             
  258.             if (clobbered != 0) {
  259.                 GC_err_printf0(
  260.                     "GC_check_heap_block: found smashed object at ");
  261.                 GC_print_smashed_obj((ptr_t)p, clobbered);
  262.             }
  263.         }
  264.         word_no += sz;
  265.         p += sz;
  266.     } while( p <= plim );
  267. }
  268.  
  269.  
  270. /* This assumes that all accessible objects are marked, and that    */
  271. /* I hold the allocation lock.    Normally called by collector.        */
  272. void GC_check_heap()
  273. {
  274.     GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
  275. }
  276.  
  277. struct closure {
  278.     GC_finalization_proc cl_fn;
  279.     extern_ptr_t cl_data;
  280. };
  281.  
  282. # ifdef __STDC__
  283.     void * GC_make_closure(GC_finalization_proc fn, void * data)
  284. # else
  285.     extern_ptr_t GC_make_closure(fn, data)
  286.     GC_finalization_proc fn;
  287.     extern_ptr_t data;
  288. # endif
  289. {
  290.     struct closure * result =
  291.             (struct closure *) GC_malloc(sizeof (struct closure));
  292.     
  293.     result -> cl_fn = fn;
  294.     result -> cl_data = data;
  295.     return((extern_ptr_t)result);
  296. }
  297.  
  298. # ifdef __STDC__
  299.     void GC_debug_invoke_finalizer(void * obj, void * data)
  300. # else
  301.     void GC_debug_invoke_finalizer(obj, data)
  302.     char * obj;
  303.     char * data;
  304. # endif
  305. {
  306.     register struct closure * cl = (struct closure *) data;
  307.     
  308.     (*(cl -> cl_fn))((extern_ptr_t)((char *)obj + sizeof(oh)), cl -> cl_data);
  309.  
  310.